package com.vito.support;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vito.framework.base.exception.CommonException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class ApiResponse<T> {
    private static Logger logger = LoggerFactory.getLogger(ApiResponse.class);

    @JSONField(ordinal = 1)
    private int code;

    @JSONField(name = "message", ordinal = 2)
    private String message;

    @JSONField(ordinal = 3)
    private T data;

    public static <T> ApiResponse of(Exception e) {
        ApiResponse response;
        if (e instanceof CommonException) {
            CommonException ex = (CommonException) e;
            response = of(ex.getResultEnum());
        }
        else if (e instanceof DataAccessException) {
            response = of(ResultEnum.DATA_ACCESS_ERROR);
        } else if (e instanceof SQLException) {
            response = of(ResultEnum.DATA_ACCESS_ERROR);
        } else {
            String message = e != null ? e.getMessage() : null;
            response = of(ResultEnum.FAIL);
            if (!StringUtils.isEmpty(message)) {
                response.setMessage(message);
            }
        }

        logger.error(response.getMessage(), e);

        return response;
    }

    public static <T> ApiResponse of(ResultEnum resultEnum) {
        return of(resultEnum, (T) null);
    }

    public static <T> ApiResponse ofPage(int page, int limit, int total, T list) {
        Map<String, Object> result = new HashMap<>(4);
        result.put("page", page);
        result.put("limit", limit);
        result.put("total", total);
        result.put("list", list);

        return ok(result);
    }

    public static <T> ApiResponse ofPage(IPage<T> data) {
        Map<String, Object> result = new HashMap<>(4);
        result.put("page", data.getCurrent());
        result.put("limit", data.getPages());
        result.put("total", data.getTotal());
        result.put("list", data.getRecords());
        return ok(result);
    }

    public static <T> ApiResponse ok(T data) {
        return of(ResultEnum.OK, data);
    }

    public static <T> ApiResponse of(ResultEnum resultEnum, T data) {
        if (resultEnum == null) {
            resultEnum = ResultEnum.UNKNOWN;
        }

        return new ApiResponse<T>(resultEnum.getCode(), resultEnum.getMessage(), data);
    }

    public static <T> ApiResponse of(int code, String message, T data) {
        
        return new ApiResponse<T>(code, message, data);
    }

    public static <T> ApiResponse of(int code, String message) {
        
        return new ApiResponse<T>(code, message, null);
    }
    
    public static <T> ApiResponse copy(JSONObject res) {
        
        return ApiResponse.of(res.getIntValue("code"), res.getString("message"), res.get("data"));
    }
    private ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public T getData() {
        return data;
    }

    public ApiResponse withMessage(String message) {
        if (!StringUtils.isEmpty(message)) {
            message = this.message + ", " + message;
        }
        setMessage(message);

        return this;
    }

    public ApiResponse setMessage(String message) {
        this.message = message;

        return this;
    }

    public void sendRedirect(HttpServletResponse response, String url) throws IOException {
        if (StringUtils.isEmpty(url)) return;

        JSONObject.toJSONString(this);

        response.sendRedirect(url);
    }
}
